/*
 * sank.cpp
 *
 *  Created on: 2022年4月6日
 *      Author: laplace
 * WASD 上下左右
 * Q加速，死了就重开
 */
#include <iostream>
#include <conio.h>
#include <graphics.h>		// 引用 EasyX 绘图库头文件
#include "stdlib.h"
#include "io.h"
#include "string.h"
//游戏窗口大小
#define GAME_RANGEX 640
#define GAME_RANGEY 480
//键值设置
#define S_LEFT 97
#define S_UP	119
#define S_RIGHT 100
#define S_DOWN 115
//加速键
#define S_QUICK 113

//蛇身体，x，y为每一节坐标，next指向后面的一节身体，before指向前面一节身体
typedef struct _snake_body {
	int x;
	int y;
	struct _snake_body* next;
	struct _snake_body* before;
}snake_body_t;
//蛇链表结构体
typedef struct _snake_list {
	snake_body_t* head;	//蛇头指针，更改值会找不到尾巴
	snake_body_t* tail;	//蛇尾巴，当作变量使用，运行find_tail()后就是尾巴
	char width;			//蛇宽度
	int driction;		//蛇运动朝向
	int len;			//蛇长度节
}snake_t;
//蛋结构体
typedef struct egg {
	int x;
	int y;
	char size;
}egg_t;

//初始化蛇吃的蛋，随机坐标
void create_egg(egg_t* e,int width) {
	e->size = width;
	e->x = rand() % GAME_RANGEX/ width * width;
	e->y = rand() % GAME_RANGEY / width * width;
	
}
//创建长度为len，宽为width的蛇，初始头坐标为x，y
snake_t* create_snake(int len, int x, int y,int width)
{
	snake_t* s = (snake_t*)malloc(sizeof(snake_t)+1);
	snake_body_t* head;
	snake_body_t* p;
	head = (snake_body_t*)malloc(sizeof(snake_body_t) * (len+1));
	s->len = len;
	s->head = head;
	s->width = width;
	s->driction = S_UP;
	int i = 0;
	p = head;
	s->driction = 1;
	for (; i < s->len; i++)
	{
		p->x = x - i*width;
		p->y = y;
		p->next = p + 1;
		p = p->next;
		p->before = p - 1;
	}
	return s;
}

snake_body_t* find_head(snake_t* s)
{
	return s->head;
}
//根据蛇头找到蛇尾
snake_body_t* find_tail(snake_t* s)
{
	snake_body_t* tail = s->head;
	int i = 0;
	for (; i < s->len - 1; i++)
	{
		tail = tail->next;
	}
	s->tail = tail;
	return tail;
}
//给蛇加len的长度
snake_t* add_snake_len(snake_t* s, int add_len)
{
	find_tail(s);
	snake_t* add_s = create_snake(s->tail->x, s->tail->y, add_len,s->width);
	s->tail->next = add_s->head;
	add_s->head->before = s->tail;
	s->len += add_len;
	return s;
}
//在x,y位置画矩形，长宽为width-2
void draw_xy(int x, int y,int width)
{
	fillrectangle(x, y, x + width-2, y + width-2);
}
//绘制游戏窗口
void ui_init()
{
	initgraph(GAME_RANGEX, GAME_RANGEY);
}
//获取蛇的按键值ch：获取到的键值，
//返回值：蛇的方向
int get_key(int* ch)
{	
	static int key=S_UP;
	//int ch = *p;
	if (_kbhit()) {//如果有按键按下，则_kbhit()函数返回真
		*ch = _getch();//使用_getch()函数获取按下的键值
		if ((*ch == S_UP && key!=S_DOWN) || (*ch == S_DOWN && key!=S_UP)
			|| (*ch == S_LEFT && key!=S_RIGHT) || (*ch == S_RIGHT && key!=S_LEFT))key = *ch;
		printf("key:%d\n", *ch);
	}
	return key;
}

void place_egg(egg_t* e)
{
	draw_xy(e->x, e->y,e->size);
}
//画蛇
void draw_snake(snake_t* s)
{
	snake_body_t* b = s->head;
	int i = 0;
	for (; i < s->len; i++)
	{
		draw_xy(b->x, b->y,s->width);
		//printf("xy:%d,%d\n",b->x,b->y);
		b = b->next;
	}
}
//&& (p->y < e->y - e->size)
//判断是否咬到自己
char if_die(snake_t* s)
{
	snake_body_t* p;
	int i=0;
	p=find_tail(s);
	for(;i < s->len-2;i++)
	{
		if ((s->head->x == p->x) && (s->head->y == p->y))return 1;
		p = p->before;
	}
	return 0;
}
//判断是否吃到蛋
char if_eat_egg(egg_t* e, snake_t* s)
{
	int i = 0;
	snake_body_t* p = s->head;
	for (; i < s->len - 1; i++) {
		if ((p->x == e->x) &&(e->y == p->y) ) {
			add_snake_len(s, 2);
			create_egg(e,s->width);
			p = p->next;
			return 1;
		}
	}
	return 0;
}
//蛇向driction移动一格
void snake_go(snake_t* s)
{
	static int last_key;
	int i = 0;
	find_tail(s);
	//限制蛇的范围
	if (s->head->x > GAME_RANGEX)s->head->x = 0;
	if (s->head->x < 0)s->head->x = GAME_RANGEX;
	if (s->head->y > GAME_RANGEY)s->head->y = 0;
	if (s->head->y < 0)s->head->y = GAME_RANGEY;
	//将蛇的每一格都向前移动到前一格
	for (; i < s->len - 1; i++)
	{
		s->tail->x = s->tail->before->x;
		s->tail->y = s->tail->before->y;
		s->tail = s->tail->before;
	}
	//将蛇头向driction移动
	switch (s->driction)
	{
		case S_UP:	 s->head->y = s->head->y - s->width;break;		
		case S_DOWN:s->head->y = s->head->y + s->width;break;		
		case S_RIGHT:s->head->x = s->head->x + s->width; break;
		case S_LEFT:s->head->x = s->head->x - s->width; break;
	}
}

int main()
{
	snake_t* s = create_snake(5, 80, 80,10);
	egg_t e;
	int key;
	int time=100;
	char str[5];
	ui_init();
	create_egg(&e,10);
		BeginBatchDraw();//防闪烁第一步
	while (1)
	{		
		cleardevice();//清屏
		s->driction = get_key(&key);
		//判断加速
			if (key == S_QUICK){
				time = 50;
			}
			else {
				time = 100;
			}
			//蛇移动
			snake_go(s);
			if (if_die(s)){
				free(s); s = create_snake(5, 80, 80, 10);//死了重新生成蛇
			} 
			//画蛇
			draw_snake(s);
			if (if_eat_egg(&e, s) == 0) {
				draw_xy(e.x, e.y,e.size);
			}
			Sleep(time);
			 FlushBatchDraw();//防闪烁第二步
			
	}
	 EndBatchDraw();//结束
	free(s);
	return 0;

}
